﻿using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
using System.IO;

namespace KeelKit.Generators
{
    public enum cfLangType
    {
        CSharp, VBDotNet
    }
   public  class BaseGengerator
    {
       protected  CodeCompileUnit ccu = new CodeCompileUnit();
       protected CodeNamespace cns = null;
       protected CodeTypeDeclaration ctd = null;
       protected  BaseGengerator(string cfNameSpace)
        {
            cns = new CodeNamespace(cfNameSpace);
            cns.Imports.Add(new CodeNamespaceImport("System"));
            cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            cns.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));
            cns.Imports.Add(new CodeNamespaceImport("System.Data"));
            cns.Imports.Add(new CodeNamespaceImport("System.Text"));
            cns.Imports.Add(new CodeNamespaceImport("Keel.ORM"));
            cns.Comments.Add(new CodeCommentStatement("生成日期:" + DateTime.Now.ToString("yyyyMMddHHmmss")));
            ccu.Namespaces.Add(cns);
        }
 
         public bool AddProperty(string name, Type type, CodeAttributeDeclaration cad,string desc)
       {
           bool  i = false  ;
           try
           {
               CodeMemberField cmf = new CodeMemberField(type, "_" + name);
               CodeMemberProperty cmp = new CodeMemberProperty();
               cmp.Name = name;
               cmp.CustomAttributes.Add(cad);
               cmp.Type = new CodeTypeReference(type);
               cmp.Attributes = (cmp.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Public;
               cmp.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_" + name)));
               cmp.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_" + name), new CodePropertySetValueReferenceExpression()));
               if (desc != null || desc.Trim() != "")
               {
                   cmf.Comments.Add(new CodeCommentStatement(desc));
                   cmp.Comments.Add(new CodeCommentStatement(desc));
               }
               ctd.Members.Add(cmf);
               ctd.Members.Add(cmp);
               i = true ;
           }
           catch (Exception)
           {
               i = false;
           }
           return i;
       }

       public bool AddProperty(string name, Type type,string desc)
       {
           bool i = false;
           try
           {
               CodeAttributeDeclaration cad = new CodeAttributeDeclaration(
                        new CodeTypeReference(typeof(Keel.ORM.DataFieldAttribute)),
                        new CodeAttributeArgument(new CodePrimitiveExpression(name))
                        );
               i = AddProperty(name, type, cad,desc );
           }
           catch (Exception)
           {
               i = false;
           }
           return i;
       }
        public string Save(string path, cfLangType clt)
        {

            CodeDomProvider provider = null;
            switch (clt)
            {
                default:
                case cfLangType.CSharp:
                    provider = new CSharpCodeProvider();
                    break;
                case cfLangType.VBDotNet:
                    provider = new VBCodeProvider();
                    break;
            }

            string filename = Path.GetDirectoryName(path) + "\\" + ctd.Name;
            if (provider.FileExtension[0] == '.')
            {
                filename += provider.FileExtension;
            }
            else
            {
                filename += "." + provider.FileExtension;
            }
            if (System.IO.File.Exists(filename))
            {
                if (System.IO.File.GetAttributes(filename) != FileAttributes.Normal)
                {
                    System.IO.File.SetAttributes(filename, FileAttributes.Normal);
                }
            }
         

            IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(filename, false, Encoding.UTF8  ), "    ");
            provider.GenerateCodeFromCompileUnit(ccu, tw, new CodeGeneratorOptions());
            tw.Close();
            return filename;
        }
    }
}
